home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / DBL Pascal Library / Queues / PriorityQueue next >
Text File  |  1993-03-29  |  5KB  |  162 lines

  1. unit PriorityQueue;
  2.  
  3. {This unit implements a priority queue. This is cribbed from "Data Structures and}
  4. {Algorithms", Aho, Hopcroft, and Ullman, Addison-Wesley, 1983 (corrected 1987 edition).}
  5.  
  6. interface
  7.  
  8.     type
  9.         PriorityQueueItem = record
  10.                 data: Longint;
  11.                 priority: Longint;
  12.             end;
  13.         PriorityQueue = record
  14.                 Qsize, Qlast: Integer;
  15.                 Qelts: array[1..1] of PriorityQueueItem;
  16.             end;
  17.         PriorityQueuePtr = ^PriorityQueue;
  18.         PriorityQueueHandle = ^PriorityQueuePtr;
  19.  
  20.     procedure NewPriorityQueue (itsSize: Integer;
  21.                                     var theQueue: PriorityQueueHandle);
  22.     procedure DisposePriorityQueue (theQueue: PriorityQueueHandle);
  23.     procedure FlushPriorityQueue (theQueue: PriorityQueueHandle);
  24.  
  25.     function PriorityQueueFull (theQueue: PriorityQueueHandle): Boolean;
  26.     function PriorityQueueEmpty (theQueue: PriorityQueueHandle): Boolean;
  27.  
  28.     procedure PriorityQueueInsert (item: univ Longint;
  29.                                     itemPriority: Longint;
  30.                                     theQueue: PriorityQueueHandle);
  31.     procedure PriorityQueueDeleteMin (var item: univ Longint;
  32.                                     var itemPriority: Longint;
  33.                                     theQueue: PriorityQueueHandle);
  34.  
  35.  
  36. implementation
  37.  
  38. {Array implementation of priority queue implements balanced tree as a heap (not to be}
  39. {confused with the Mac's memory space). If we call array A, the root of the tree is at}
  40. {A[1], and for i > 1, the parent of A[i] is A[i div 2]. The priority of a given node is no}
  41. {greater than the priority of both its children.}
  42.  
  43. {Using a heap rather than a real tree costs us a slight overhead in integer multiplication}
  44. {and division, but saves us a lot of time in creating and deleting nodes. The complexity}
  45. {is O(log n) regardless of representation.}
  46.  
  47.     procedure FlushPriorityQueue (theQueue: PriorityQueueHandle);
  48.     begin
  49.         theQueue^^.Qlast := 0;
  50.     end;
  51.  
  52.     procedure NewPriorityQueue (itsSize: Integer;
  53.                                     var theQueue: PriorityQueueHandle);
  54.     begin
  55.         theQueue := PriorityQueueHandle(NewHandle(SIZEOF(PriorityQueue) + (itsSize - 1) * SIZEOF(PriorityQueueItem)));
  56.         theQueue^^.Qsize := itsSize;
  57.         FlushPriorityQueue(theQueue);
  58.     end;
  59.  
  60.     procedure DisposePriorityQueue (theQueue: PriorityQueueHandle);
  61.     begin
  62.         DisposHandle(Handle(theQueue));
  63.     end;
  64.  
  65.     function PriorityQueueFull (theQueue: PriorityQueueHandle): Boolean;
  66.     begin
  67.         with theQueue^^ do
  68.             PriorityQueueFull := Qlast = Qsize;
  69.     end;
  70.  
  71.     function PriorityQueueEmpty (theQueue: PriorityQueueHandle): Boolean;
  72.     begin
  73.         PriorityQueueEmpty := theQueue^^.Qlast = 0;
  74.     end;
  75.  
  76.     procedure Swap (var a, b: PriorityQueueItem);
  77.         var
  78.             temp: PriorityQueueItem;
  79.     begin
  80.         temp := a;
  81.         a := b;
  82.         b := temp;
  83.     end;
  84.  
  85.     procedure PriorityQueueInsert (item: univ Longint;
  86.                                     itemPriority: Longint;
  87.                                     theQueue: PriorityQueueHandle);
  88.  
  89.         var
  90.             i: Integer;
  91.     begin
  92.         if not PriorityQueueFull(theQueue) then
  93.             with theQueue^^ do
  94.                 begin
  95.                     Qlast := Qlast + 1;
  96. {$PUSH}
  97. {$R-}
  98.                     with Qelts[Qlast] do    {start with new element at bottom left of tree}
  99. {$POP}
  100.                         begin
  101.                             data := item;
  102.                             priority := itemPriority;
  103.                         end;
  104.                     i := Qlast;
  105. {$PUSH}
  106. {$R-}
  107.                     while (i > 1) & (Qelts[i].priority < Qelts[i div 2].priority) do
  108.                         begin    {repeatedly swap the new element with its parent to maintain the invariant}
  109.                             Swap(Qelts[i], Qelts[i div 2]);
  110.                             i := i div 2;
  111.                         end;
  112. {$POP}
  113.                 end;
  114.     end;
  115.  
  116.     procedure PriorityQueueDeleteMin (var item: univ Longint;
  117.                                     var itemPriority: Longint;
  118.                                     theQueue: PriorityQueueHandle);
  119.         var
  120.             i, j: Integer;
  121.             min: PriorityQueueItem;
  122.     begin
  123.         if not PriorityQueueEmpty(theQueue) then
  124.             with theQueue^^ do
  125.                 begin
  126.                     with Qelts[1] do {the easy part - minimum is in a known place}
  127.                         begin
  128.                             item := data;
  129.                             itemPriority := priority;
  130.                         end;
  131. {$PUSH}
  132. {$R-}
  133.                     Qelts[1] := Qelts[Qlast]; {replace the root with the bottom left element}
  134. {$POP}
  135.                     Qlast := Qlast - 1;
  136.                     i := 1; {the old last element is in the wrong place now, so let's track it}
  137.                     while i <= Qlast div 2 do
  138.                         begin {push the old last element down the tree to its proper place}
  139. {$PUSH}
  140. {$R-}
  141.                             if (Qelts[2 * i].priority < Qelts[2 * i + 1].priority) or (2 * i = Qlast) then
  142. {$POP}
  143.                                 j := 2 * i
  144.                             else
  145.                                 j := 2 * i + 1;
  146.                         {j is either the child of i having the lower priority,}
  147.                         {or is last and the only child of i}
  148. {$PUSH}
  149. {$R-}
  150.                             if Qelts[i].priority > Qelts[j].priority then
  151.                                 begin {swap old last element with its lower priority child…}
  152.                                     Swap(Qelts[i], Qelts[j]);
  153.                                     i := j;
  154.                                 end
  155.                             else
  156.                                 Leave; {…or, leave if the priority is now correct}
  157. {$POP}
  158.                         end;
  159.                 end;
  160.     end;
  161.  
  162. end.